`include "cpu_def.vh"

module backend (
  input clk,
  input rst,
  input [5:0] ext_int,

  // frontend
  input        if_out_valid       ,
  input [31:0] if_out_pc          ,
  input [31:0] if_out_instr       ,
  input        if_out_ft_tlbre    ,
  input        if_out_ft_tlbi     ,
  input        if_out_ft_adel     ,
  input        if_out_br_pre_taken,
  input [31:0] if_out_br_pre_pc   ,
  output       frontend_stall     ,
  output       frontend_flush     ,  
  
  output        backend_redirect_taken,
  output        backend_redirect_is_br,
  output [31:0] backend_redirect_pc   ,
  output [31:0] backend_redirect_ds_pc,

  output        backend_branch          ,
  output        backend_branch_taken    ,
  output [31:0] backend_branch_pc       ,
  output [31:0] backend_branch_target_pc,

  // mmu
  output dtlb0_flush,
  output dtlb0_stall,

  output [31:0] data_vaddr ,
  output        data_vaddr_valid,
  output        is_store   ,
  output        tlbwi_taken,
  output        tlbwr_taken,

  input        data_uncache     ,
  input [31:0] data_paddr       ,
  input        data_paddr_valid ,
  input        data_tlb_refill  ,
  input        data_tlb_invalid ,
  input        data_tlb_modified,

  output [31:0] cp0_index_rdata   ,
  output [31:0] cp0_random_rdata  ,
  output [31:0] cp0_entrylo0_rdata,
  output [31:0] cp0_entrylo1_rdata,
  output [31:0] cp0_entryhi_rdata ,
  output [31:0] cp0_config0_rdata ,

  input [31:0] cp0_index_wdata   ,
  input [31:0] cp0_entrylo0_wdata,
  input [31:0] cp0_entrylo1_wdata,
  input [31:0] cp0_entryhi_wdata ,

  // data_stram interface
  output data_sram_uncache,
  output data_sram_req    ,
  input  data_sram_addr_ok,

  output        data_sram_wr   ,
  output [ 1:0] data_sram_size ,
  output [31:0] data_sram_addr ,
  output [ 3:0] data_sram_wstrb,
  output [31:0] data_sram_wdata,

  input        data_sram_data_ok,
  input [31:0] data_sram_rdata  ,

  // debug interface
  (*mark_debug = "true"*)output [31:0] debug_wb_pc      ,
  (*mark_debug = "true"*)output [ 3:0] debug_wb_rf_wen  ,
  (*mark_debug = "true"*)output [ 4:0] debug_wb_rf_wnum ,
  (*mark_debug = "true"*)output [31:0] debug_wb_rf_wdata
);
  // decode
  wire                   de_out_valid          ;
  wire [           31:0] de_out_pc             ;
  wire                   de_out_br_pre_taken   ;
  wire [           31:0] de_out_br_pre_pc      ;
  wire [           31:0] de_out_rf_rdata_0     ;
  wire [           31:0] de_out_rf_rdata_1     ;
  wire [           31:0] de_out_hl_rdata       ;
  wire [            4:0] de_out_rs             ;
  wire [            4:0] de_out_rt             ;
  wire [            4:0] de_out_rd             ;
  wire [            4:0] de_out_sa             ;
  wire [           31:0] de_out_simm           ;
  wire [           31:0] de_out_uimm           ;
  wire [           31:0] de_out_addr           ;
  wire [           12:0] de_out_alu_op         ;
  wire                   de_out_sel_alu_src_0  ;
  wire [            1:0] de_out_sel_alu_src_1  ;
  wire [            1:0] de_out_sel_rf_waddr   ;
  wire [            1:0] de_out_sel_br_target  ;
  wire                   de_out_sel_hl_wdata_ex;
  wire                   de_out_read_mem       ;
  wire                   de_out_write_mem      ;
  wire                   de_out_branch         ;
  wire [`NR_LD_OP - 1:0] de_out_ld_op          ;
  wire [`NR_ST_OP - 1:0] de_out_st_op          ;
  wire [`NR_BR_OP - 1:0] de_out_br_op          ;
  wire                   de_out_mul            ;
  wire                   de_out_mul_sign       ;
  wire                   de_out_div            ;
  wire                   de_out_div_sign       ;
  wire                   de_out_chk_ov         ;
  wire [           31:0] de_out_br_target      ;
  wire [           31:0] de_out_jp_target      ;

  wire                   de_out_write_rf       ;
  wire [            2:0] de_out_sel_rf_wdata   ;
  wire [            1:0] de_out_write_hl       ;
  wire                   de_out_sel_hl_wdata   ;
  wire [            2:0] de_out_cp0_wsel       ;
  wire                   de_out_cp0_wen        ;
  wire [           31:0] de_out_cp0_rdata      ;
  wire                   de_out_ft_tlbre       ;
  wire                   de_out_ft_tlbi        ;
  wire                   de_out_ft_adel        ;
  wire                   de_out_sys            ;
  wire                   de_out_brk            ;
  wire                   de_out_ri             ;
  wire                   de_out_eret           ;
  wire                   de_out_tlbp           ;
  wire                   de_out_tlbr           ;
  wire                   de_out_tlbwi          ;
  wire                   de_out_tlbwr          ;
  // execute
  wire                   ex_in_valid          ;
  wire [           31:0] ex_in_pc             ;
  wire                   ex_in_br_pre_taken   ;
  wire [           31:0] ex_in_br_pre_pc      ;
  wire [           31:0] ex_in_rf_rdata_0     ;
  wire [           31:0] ex_in_rf_rdata_1     ;
  wire [           31:0] ex_in_hl_rdata       ;
  wire [            4:0] ex_in_rs             ;
  wire [            4:0] ex_in_rt             ;
  wire [            4:0] ex_in_rd             ;
  wire [            4:0] ex_in_sa             ;
  wire [           31:0] ex_in_simm           ;
  wire [           31:0] ex_in_uimm           ;
  wire [           31:0] ex_in_addr           ;
  wire [           12:0] ex_in_alu_op         ;
  wire                   ex_in_sel_alu_src_0  ;
  wire [            1:0] ex_in_sel_alu_src_1  ;
  wire [            1:0] ex_in_sel_rf_waddr   ;
  wire [            1:0] ex_in_sel_br_target  ;
  wire                   ex_in_sel_hl_wdata_ex;
  wire                   ex_in_read_mem       ;
  wire                   ex_in_write_mem      ;
  wire                   ex_in_branch         ;
  wire [`NR_LD_OP - 1:0] ex_in_ld_op          ;
  wire [`NR_ST_OP - 1:0] ex_in_st_op          ;
  wire [`NR_BR_OP - 1:0] ex_in_br_op          ;
  wire                   ex_in_mul            ;
  wire                   ex_in_mul_sign       ;
  wire                   ex_in_chk_ov         ;
  wire [           31:0] ex_in_br_target      ;
  wire [           31:0] ex_in_jp_target      ;

  wire                   ex_in_div            ;
  wire                   ex_in_div_sign       ;
  wire                   ex_in_write_rf       ;
  wire [            2:0] ex_in_sel_rf_wdata   ;
  wire [            1:0] ex_in_write_hl       ;
  wire                   ex_in_sel_hl_wdata   ;
  wire [            2:0] ex_in_cp0_wsel       ;
  wire                   ex_in_cp0_wen        ;
  wire [           31:0] ex_in_cp0_rdata      ;
  wire                   ex_in_ft_tlbre       ;
  wire                   ex_in_ft_tlbi        ;
  wire                   ex_in_ft_adel        ;
  wire                   ex_in_sys            ;
  wire                   ex_in_brk            ;
  wire                   ex_in_ri             ;
  wire                   ex_in_eret           ;
  wire                   ex_in_tlbp           ;
  wire                   ex_in_tlbr           ;
  wire                   ex_in_tlbwi          ;
  wire                   ex_in_tlbwr          ;

  wire        ex_out_valid       ;
  wire [31:0] ex_out_pc          ;
  wire [31:0] ex_out_alu_result  ;
  wire [63:0] ex_out_div_rs      ;
  wire        ex_out_wr_mem      ;
  wire        ex_out_write_rf    ;
  wire [ 4:0] ex_out_rf_waddr    ;
  wire [ 2:0] ex_out_sel_rf_wdata;
  wire [ 1:0] ex_out_write_hl    ;
  wire        ex_out_sel_hl_wdata;
  wire [ 2:0] ex_out_cp0_wsel    ;
  wire [ 4:0] ex_out_cp0_wreg_num;
  wire        ex_out_cp0_wen     ;
  wire [31:0] ex_out_cp0_wdata   ;
  wire [31:0] ex_out_cp0_rdata   ;
  wire        ex_out_ft_tlbre    ;
  wire        ex_out_ft_tlbi     ;
  wire        ex_out_sys         ;
  wire        ex_out_brk         ;
  wire        ex_out_ov          ;
  wire        ex_out_adel        ;
  wire        ex_out_ades        ;
  wire        ex_out_tlbrel      ;
  wire        ex_out_tlbres      ;
  wire        ex_out_tlbil       ;
  wire        ex_out_tlbis       ;
  wire        ex_out_tlbm        ;
  wire        ex_out_ft_adel     ;
  wire        ex_out_ri          ;
  wire        ex_out_int         ;
  wire [31:0] ex_out_badvaddr    ;
  wire        ex_out_eret        ;
  wire        ex_out_bd          ;
  wire        ex_out_tlbp        ;
  wire        ex_out_tlbr        ;
  wire        ex_out_tlbwi       ;
  wire        ex_out_tlbwr       ;
  
  wire [31:0] br_mispre_pc   ;
  wire [31:0] br_ds_pc       ;
  wire        br_mispre_taken;
  wire        br_mispre_is_br;

  wire ex_redirect_taken;
  wire [31:0] ex_redirect_pc;

  wire ex_ld;
  wire ex_mul;

  wire ex_out_ex_taken;
  wire ex_out_eret_taken;
  // write back
  wire        wb_in_valid       ;
  wire [31:0] wb_in_pc          ;
  wire [31:0] wb_in_alu_result  ;
  wire [63:0] wb_in_div_rs      ;
  wire        wb_in_wr_mem      ;
  wire        wb_in_write_rf    ;
  wire [ 4:0] wb_in_rf_waddr    ;
  wire [ 2:0] wb_in_sel_rf_wdata;
  wire [ 1:0] wb_in_write_hl    ;
  wire        wb_in_sel_hl_wdata;
  wire [ 2:0] wb_in_cp0_wsel    ;
  wire [ 4:0] wb_in_cp0_wreg_num;
  wire        wb_in_cp0_wen     ;
  wire [31:0] wb_in_cp0_wdata   ;
  wire [31:0] wb_in_cp0_rdata   ;
  wire        wb_in_ft_tlbre    ;
  wire        wb_in_ft_tlbi     ;
  wire        wb_in_sys         ;
  wire        wb_in_brk         ;
  wire        wb_in_ov          ;
  wire        wb_in_adel        ;
  wire        wb_in_ades        ;
  wire        wb_in_tlbrel      ;
  wire        wb_in_tlbres      ;
  wire        wb_in_tlbil       ;
  wire        wb_in_tlbis       ;
  wire        wb_in_tlbm        ;
  wire        wb_in_ft_adel     ;
  wire        wb_in_ri          ;
  wire        wb_in_int         ;
  wire [31:0] wb_in_badvaddr    ;
  wire        wb_in_eret        ;
  wire        wb_in_bd          ;
  wire        wb_in_tlbp        ;
  wire        wb_in_tlbr        ;
  wire        wb_in_tlbwi       ;
  wire        wb_in_tlbwr       ;
  
  wire [31:0] wb_out_pc      ;
  wire        wb_out_rf_wen  ;
  wire [ 4:0] wb_out_rf_wnum ;
  wire [31:0] wb_out_rf_wdata;
  wire [ 1:0] wb_out_hl_wen  ;
  wire [63:0] wb_out_hl_wdata;

  wire        wb_out_bd          ;
  wire        wb_out_tlbre_taken ;
  wire        wb_out_ex_taken    ;
  wire        wb_out_eret_taken  ;
  wire [ 4:0] wb_out_ex_code     ;
  wire        wb_out_cp0_wen     ;
  wire [ 4:0] wb_out_cp0_wreg_num;
  wire [ 2:0] wb_out_cp0_wsel    ;
  wire [31:0] wb_out_cp0_wdata   ;
  wire [31:0] wb_out_addr        ;
  wire        wb_out_tlbp_taken  ;
  wire        wb_out_tlbr_taken  ;
  wire        wb_out_tlbwi_taken ;
  wire        wb_out_tlbwr_taken ;

  wire [31:0] wb_out_tlb_pc;

  wire        wb_out_write_rf;
  wire [31:0] wb_out_write_rf_data;
  wire [ 1:0] wb_out_write_hl;

  wire wb_out_ld;
  wire wb_out_mul;
  // forward path
  wire        wb_rf_wen        ;
  wire [ 4:0] wb_rf_wnum       ;
  wire [31:0] wb_rf_wdata      ;
  wire        ex_rf_wen        ;
  wire [ 4:0] ex_rf_wnum       ;
  wire [31:0] ex_rf_wdata      ;
  wire [ 4:0] de_rs            ;
  wire [ 4:0] de_rt            ;
  wire [ 1:0] de_sel_rf_rdata_0;
  wire [ 1:0] de_sel_rf_rdata_1;
  wire [31:0] forward_data_ex  ;
  wire [31:0] forward_data_wb  ;
  // hi li forward path
  wire [ 1:0] sel_hl_rdata;
  wire [31:0] hl_rdata_ex ;
  wire [31:0] hl_rdata_wb ;
  // hazard
  wire       stall_req_wb;
  wire       stall_req_de;
  wire       stall_req_ex;
  wire       flush_req_wb;
  wire       flush_req_ex;
  wire [3:0] stall;
  wire [2:0] flush;
  // multiplier
  wire [31:0] mul_x     ;
  wire [31:0] mul_y     ;
  wire        mul_sign  ;
  wire [63:0] mul_result;

  wire                   lsu_valid_i  ;
  wire                   lsu_read_mem ;
  wire                   lsu_write_mem;
  wire [`NR_LD_OP - 1:0] lsu_ld_op    ;
  wire [`NR_ST_OP - 1:0] lsu_st_op    ;
  wire [           31:0] lsu_addr     ;
  wire [           31:0] lsu_rt       ;
  wire                   lsu_ex_taken ;

  wire                   lsu_valid_o  ;
  wire [           31:0] lsu_ld_data  ;
  wire                   lsu_adel     ;
  wire                   lsu_ades     ;
  wire                   lsu_tlbrel   ;
  wire                   lsu_tlbres   ;
  wire                   lsu_tlbil    ;
  wire                   lsu_tlbis    ;
  wire                   lsu_tlbm     ;
  wire [           31:0] lsu_badvaddr ;

  wire lsu_stall_ex;
  wire lsu_stall_wb;
  // regfile
  wire [ 4:0] rf_raddr_0;
  wire [ 4:0] rf_raddr_1;
  wire [31:0] rf_rdata_0;
  wire [31:0] rf_rdata_1;
  // hi lo
  wire [ 1:0] hi_lo_raddr;
  wire [31:0] hi_lo_rdata;
  // cp0 
  wire [31:0] cp0_ex_pc;
  wire [ 2:0] cp0_rsel    ;
  wire [ 4:0] cp0_rreg_num;
  wire [31:0] cp0_rdata   ;
  wire [31:0] cp0_rmask   ;
  wire [31:0] cp0_epc     ;
  wire        has_int     ;
  
  // cp0 forward path
  wire [ 1:0] sel_cp0_rdata;
  wire [31:0] cp0_rdata_ex;
  wire [31:0] cp0_rdata_wb;

  decode mycpu_decode(
    .clk  (clk),
    .rst  (rst),
    
    .valid_i       (if_out_valid       ),
    .pc_i          (if_out_pc          ),
    .instr_i       (if_out_instr       ),
    .ft_tlbre_i    (if_out_ft_tlbre    ),
    .ft_tlbi_i     (if_out_ft_tlbi     ),
    .ft_adel_i     (if_out_ft_adel     ),
    .br_pre_taken_i(if_out_br_pre_taken),
    .br_pre_pc_i   (if_out_br_pre_pc   ),

    .sel_rf_rdata_0_i (de_sel_rf_rdata_0),
    .sel_rf_rdata_1_i (de_sel_rf_rdata_1),
    .forward_data_ex_i(forward_data_ex  ),
    .forward_data_wb_i(forward_data_wb  ),

    .rf_raddr_0_o(rf_raddr_0),
    .rf_raddr_1_o(rf_raddr_1),
    .rf_rdata_0_i(rf_rdata_0),
    .rf_rdata_1_i(rf_rdata_1),

    .sel_hl_rdata_i(sel_hl_rdata),
    .hl_rdata_ex_i (hl_rdata_ex ),
    .hl_rdata_wb_i (hl_rdata_wb ),
    
    .hl_raddr_o(hi_lo_raddr),
    .hl_rdata_i(hi_lo_rdata),

    .sel_cp0_rdata_i(sel_cp0_rdata),
    .cp0_rdata_ex_i (cp0_rdata_ex ),
    .cp0_rdata_wb_i (cp0_rdata_wb ),

    .cp0_rsel_o    (cp0_rsel    ),
    .cp0_rreg_num_o(cp0_rreg_num),
    .cp0_rdata_i   (cp0_rdata   ),
    .cp0_rmask_i   (cp0_rmask   ),

    .valid_o          (de_out_valid          ),
    .pc_o             (de_out_pc             ),
    .br_pre_taken_o   (de_out_br_pre_taken   ),
    .br_pre_pc_o      (de_out_br_pre_pc      ),
    .rf_rdata_0_o     (de_out_rf_rdata_0     ),
    .rf_rdata_1_o     (de_out_rf_rdata_1     ),
    .hl_rdata_o       (de_out_hl_rdata       ),
    .rs_o             (de_out_rs             ),
    .rt_o             (de_out_rt             ),
    .rd_o             (de_out_rd             ),
    .sa_o             (de_out_sa             ),
    .simm_o           (de_out_simm           ),
    .uimm_o           (de_out_uimm           ),
    .addr_o           (de_out_addr           ),
    .alu_op_o         (de_out_alu_op         ),
    .sel_alu_src_0_o  (de_out_sel_alu_src_0  ),
    .sel_alu_src_1_o  (de_out_sel_alu_src_1  ),
    .sel_rf_waddr_o   (de_out_sel_rf_waddr   ),
    .sel_br_target_o  (de_out_sel_br_target  ),
    .sel_hl_wdata_ex_o(de_out_sel_hl_wdata_ex),
    .read_mem_o       (de_out_read_mem       ),
    .write_mem_o      (de_out_write_mem      ),
    .branch_o         (de_out_branch         ),
    .ld_op_o          (de_out_ld_op          ),
    .st_op_o          (de_out_st_op          ),
    .br_op_o          (de_out_br_op          ),
    .mul_o            (de_out_mul            ),
    .mul_sign_o       (de_out_mul_sign       ),
    .div_o            (de_out_div            ),
    .div_sign_o       (de_out_div_sign       ),
    .chk_ov_o         (de_out_chk_ov         ),
    .br_target_o      (de_out_br_target      ),
    .jp_target_o      (de_out_jp_target      ),

    .write_rf_o       (de_out_write_rf       ),
    .sel_rf_wdata_o   (de_out_sel_rf_wdata   ),
    .write_hl_o       (de_out_write_hl       ),
    .sel_hl_wdata_o   (de_out_sel_hl_wdata   ),
    .cp0_wsel_o       (de_out_cp0_wsel       ),
    .cp0_wen_o        (de_out_cp0_wen        ),
    .cp0_rdata_o      (de_out_cp0_rdata      ),
    .ft_tlbre_o       (de_out_ft_tlbre       ),
    .ft_tlbi_o        (de_out_ft_tlbi        ),
    .ft_adel_o        (de_out_ft_adel        ),
    .sys_o            (de_out_sys            ),
    .brk_o            (de_out_brk            ),
    .ri_o             (de_out_ri             ),
    .eret_o           (de_out_eret           ),
    .tlbp_o           (de_out_tlbp           ),
    .tlbr_o           (de_out_tlbr           ),
    .tlbwi_o          (de_out_tlbwi          ),
    .tlbwr_o          (de_out_tlbwr          ),

    .de_rs (de_rs),
    .de_rt (de_rt),

    .stall_req_de(stall_req_de),

    .ex_ld_i (ex_ld ),
    .ex_mul_i(ex_mul),

    .wb_ld_i (wb_out_ld),
    .wb_mul_i(wb_out_mul)
  );

  de_ex_reg mycpu_de_ex_reg(
    .clk(clk),
    .rst(rst),

    .stall(stall),
    .flush(flush),

    .de_out_valid        (de_out_valid        ),
    .de_out_pc           (de_out_pc           ),
    .de_out_br_pre_taken (de_out_br_pre_taken ),
    .de_out_br_pre_pc    (de_out_br_pre_pc    ),

    .de_out_rf_rdata_0     (de_out_rf_rdata_0     ),
    .de_out_rf_rdata_1     (de_out_rf_rdata_1     ),
    .de_out_hl_rdata       (de_out_hl_rdata       ),
    .de_out_rs             (de_out_rs             ),
    .de_out_rt             (de_out_rt             ),
    .de_out_rd             (de_out_rd             ),
    .de_out_sa             (de_out_sa             ),
    .de_out_simm           (de_out_simm           ),
    .de_out_uimm           (de_out_uimm           ),
    .de_out_addr           (de_out_addr           ),
    .de_out_alu_op         (de_out_alu_op         ),
    .de_out_sel_alu_src_0  (de_out_sel_alu_src_0  ),
    .de_out_sel_alu_src_1  (de_out_sel_alu_src_1  ),
    .de_out_sel_rf_waddr   (de_out_sel_rf_waddr   ),
    .de_out_sel_br_target  (de_out_sel_br_target  ),
    .de_out_sel_hl_wdata_ex(de_out_sel_hl_wdata_ex),
    .de_out_read_mem       (de_out_read_mem       ),
    .de_out_write_mem      (de_out_write_mem      ),
    .de_out_branch         (de_out_branch         ),
    .de_out_ld_op          (de_out_ld_op          ),
    .de_out_st_op          (de_out_st_op          ),
    .de_out_br_op          (de_out_br_op          ),
    .de_out_mul            (de_out_mul            ),
    .de_out_mul_sign       (de_out_mul_sign       ),
    .de_out_div            (de_out_div            ),
    .de_out_div_sign       (de_out_div_sign       ),
    .de_out_chk_ov         (de_out_chk_ov         ),
    .de_out_br_target      (de_out_br_target      ),
    .de_out_jp_target      (de_out_jp_target      ),

    .de_out_write_rf     (de_out_write_rf     ),
    .de_out_sel_rf_wdata (de_out_sel_rf_wdata ),
    .de_out_write_hl     (de_out_write_hl     ),
    .de_out_sel_hl_wdata (de_out_sel_hl_wdata ),
    .de_out_cp0_wsel     (de_out_cp0_wsel     ),
    .de_out_cp0_wen      (de_out_cp0_wen      ),
    .de_out_cp0_rdata    (de_out_cp0_rdata    ),
    .de_out_ft_tlbre     (de_out_ft_tlbre     ),
    .de_out_ft_tlbi      (de_out_ft_tlbi      ),
    .de_out_ft_adel      (de_out_ft_adel      ),
    .de_out_sys          (de_out_sys          ),
    .de_out_brk          (de_out_brk          ),
    .de_out_ri           (de_out_ri           ),
    .de_out_eret         (de_out_eret         ),
    .de_out_tlbp         (de_out_tlbp         ),
    .de_out_tlbr         (de_out_tlbr         ),
    .de_out_tlbwi        (de_out_tlbwi        ),
    .de_out_tlbwr        (de_out_tlbwr        ),

    .ex_in_valid          (ex_in_valid          ),
    .ex_in_pc             (ex_in_pc             ),
    .ex_in_br_pre_taken   (ex_in_br_pre_taken   ),
    .ex_in_br_pre_pc      (ex_in_br_pre_pc      ),
    .ex_in_rf_rdata_0     (ex_in_rf_rdata_0     ),
    .ex_in_rf_rdata_1     (ex_in_rf_rdata_1     ),
    .ex_in_hl_rdata       (ex_in_hl_rdata       ),
    .ex_in_rs             (ex_in_rs             ),
    .ex_in_rt             (ex_in_rt             ),
    .ex_in_rd             (ex_in_rd             ),
    .ex_in_sa             (ex_in_sa             ),
    .ex_in_simm           (ex_in_simm           ),
    .ex_in_uimm           (ex_in_uimm           ),
    .ex_in_addr           (ex_in_addr           ),
    .ex_in_alu_op         (ex_in_alu_op         ),
    .ex_in_sel_alu_src_0  (ex_in_sel_alu_src_0  ),
    .ex_in_sel_alu_src_1  (ex_in_sel_alu_src_1  ),
    .ex_in_sel_rf_waddr   (ex_in_sel_rf_waddr   ),
    .ex_in_sel_br_target  (ex_in_sel_br_target  ),
    .ex_in_sel_hl_wdata_ex(ex_in_sel_hl_wdata_ex),
    .ex_in_read_mem       (ex_in_read_mem       ),
    .ex_in_write_mem      (ex_in_write_mem      ),
    .ex_in_branch         (ex_in_branch         ),
    .ex_in_ld_op          (ex_in_ld_op          ),
    .ex_in_st_op          (ex_in_st_op          ),
    .ex_in_br_op          (ex_in_br_op          ),
    .ex_in_mul            (ex_in_mul            ),
    .ex_in_mul_sign       (ex_in_mul_sign       ),
    .ex_in_div            (ex_in_div            ),
    .ex_in_div_sign       (ex_in_div_sign       ),
    .ex_in_chk_ov         (ex_in_chk_ov         ),
    .ex_in_br_target      (ex_in_br_target      ),
    .ex_in_jp_target      (ex_in_jp_target      ),

    .ex_in_write_rf     (ex_in_write_rf     ),
    .ex_in_sel_rf_wdata (ex_in_sel_rf_wdata ),
    .ex_in_write_hl     (ex_in_write_hl     ),
    .ex_in_sel_hl_wdata (ex_in_sel_hl_wdata ),
    .ex_in_cp0_wsel     (ex_in_cp0_wsel     ),
    .ex_in_cp0_wen      (ex_in_cp0_wen      ),
    .ex_in_cp0_rdata    (ex_in_cp0_rdata    ),
    .ex_in_ft_tlbre     (ex_in_ft_tlbre     ),
    .ex_in_ft_tlbi      (ex_in_ft_tlbi      ),
    .ex_in_ft_adel      (ex_in_ft_adel      ),
    .ex_in_sys          (ex_in_sys          ),
    .ex_in_brk          (ex_in_brk          ),
    .ex_in_ri           (ex_in_ri           ),
    .ex_in_eret         (ex_in_eret         ),
    .ex_in_tlbp         (ex_in_tlbp         ),
    .ex_in_tlbr         (ex_in_tlbr         ),
    .ex_in_tlbwi        (ex_in_tlbwi        ),
    .ex_in_tlbwr        (ex_in_tlbwr        )
  );

  regfile mycpu_regfile(
    .clk(clk),
    .rst(rst),

    .raddr0(rf_raddr_0),
    .raddr1(rf_raddr_1),
    .rdata0(rf_rdata_0),
    .rdata1(rf_rdata_1),

    .we   (wb_out_rf_wen  ),
    .waddr(wb_out_rf_wnum ),
    .wdata(wb_out_rf_wdata)
  );

/*
  RegFile mucpu_RegFile(
    .clock(clk),
    .reset(rst),
    .io_rdPort_0_addr(rf_raddr_0),
    .io_rdPort_0_data(rf_rdata_0),
    .io_rdPort_1_addr(rf_raddr_1),
    .io_rdPort_1_data(rf_rdata_1),
    .io_wrPort_0_wen (wb_out_rf_wen  ),
    .io_wrPort_0_addr(wb_out_rf_wnum ),
    .io_wrPort_0_data(wb_out_rf_wdata)
  );
*/

  execute mycpu_execute(
    .clk(clk),
    .rst(rst),
    
    .valid_i          (ex_in_valid          ),
    .stall_i          (stall                ),
    .pc_i             (ex_in_pc             ),
    .br_pre_taken_i   (ex_in_br_pre_taken   ),
    .br_pre_pc_i      (ex_in_br_pre_pc      ),
    .rf_rdata_0_i     (ex_in_rf_rdata_0     ),
    .rf_rdata_1_i     (ex_in_rf_rdata_1     ),
    .hl_rdata_i       (ex_in_hl_rdata       ),
    .rs_i             (ex_in_rs             ),
    .rt_i             (ex_in_rt             ),
    .rd_i             (ex_in_rd             ),
    .sa_i             (ex_in_sa             ),
    .simm_i           (ex_in_simm           ),
    .uimm_i           (ex_in_uimm           ),
    .addr_i           (ex_in_addr           ),
    .alu_op_i         (ex_in_alu_op         ),
    .sel_alu_src_0_i  (ex_in_sel_alu_src_0  ),
    .sel_alu_src_1_i  (ex_in_sel_alu_src_1  ),
    .sel_rf_waddr_i   (ex_in_sel_rf_waddr   ),
    .sel_br_target_i  (ex_in_sel_br_target  ),
    .sel_hl_wdata_ex_i(ex_in_sel_hl_wdata_ex),
    .read_mem_i       (ex_in_read_mem       ),
    .write_mem_i      (ex_in_write_mem      ),
    .branch_i         (ex_in_branch         ),
    .ld_op_i          (ex_in_ld_op          ),
    .st_op_i          (ex_in_st_op          ),
    .br_op_i          (ex_in_br_op          ),
    .mul_i            (ex_in_mul            ),
    .mul_sign_i       (ex_in_mul_sign       ),
    .div_i            (ex_in_div            ),
    .div_sign_i       (ex_in_div_sign       ),
    .chk_ov_i         (ex_in_chk_ov         ),
    .br_target_i      (ex_in_br_target      ),
    .jp_target_i      (ex_in_jp_target      ),

    .write_rf_i     (ex_in_write_rf     ),
    .sel_rf_wdata_i (ex_in_sel_rf_wdata ),
    .write_hl_i     (ex_in_write_hl     ),
    .sel_hl_wdata_i (ex_in_sel_hl_wdata ),
    .cp0_wsel_i     (ex_in_cp0_wsel     ),
    .cp0_wen_i      (ex_in_cp0_wen      ),
    .cp0_rdata_i    (ex_in_cp0_rdata    ),
    .ft_tlbre_i     (ex_in_ft_tlbre     ),
    .ft_tlbi_i      (ex_in_ft_tlbi      ),
    .ft_adel_i      (ex_in_ft_adel      ),
    .sys_i          (ex_in_sys          ),
    .brk_i          (ex_in_brk          ),
    .adel_i         (lsu_adel           ),
    .ades_i         (lsu_ades           ),
    .tlbrel_i       (lsu_tlbrel         ),
    .tlbres_i       (lsu_tlbres         ),
    .tlbil_i        (lsu_tlbil          ),
    .tlbis_i        (lsu_tlbis          ),
    .tlbm_i         (lsu_tlbm           ),
    .ri_i           (ex_in_ri           ),
    .int_i          (has_int            ),
    .badvaddr_i     (lsu_badvaddr       ),
    .eret_i         (ex_in_eret         ),
    .tlbp_i         (ex_in_tlbp         ),
    .tlbr_i         (ex_in_tlbr         ),
    .tlbwi_i        (ex_in_tlbwi        ),
    .tlbwr_i        (ex_in_tlbwr        ),
    .lsu_stall_ex_i (lsu_stall_ex       ),

    .valid_o       (ex_out_valid       ),
    .pc_o          (ex_out_pc          ),
    .alu_result_o  (ex_out_alu_result  ),
    .div_rs_o      (ex_out_div_rs      ),
    .wr_mem_o      (ex_out_wr_mem      ),
    .write_rf_o    (ex_out_write_rf    ),
    .rf_waddr_o    (ex_out_rf_waddr    ),
    .sel_rf_wdata_o(ex_out_sel_rf_wdata),
    .write_hl_o    (ex_out_write_hl    ),
    .sel_hl_wdata_o(ex_out_sel_hl_wdata),
    .cp0_wsel_o    (ex_out_cp0_wsel    ),
    .cp0_wreg_num_o(ex_out_cp0_wreg_num),
    .cp0_wen_o     (ex_out_cp0_wen     ),
    .cp0_wdata_o   (ex_out_cp0_wdata   ),
    .cp0_rdata_o   (ex_out_cp0_rdata   ),
    .ft_tlbre_o    (ex_out_ft_tlbre    ),
    .ft_tlbi_o     (ex_out_ft_tlbi     ),
    .sys_o         (ex_out_sys         ),
    .brk_o         (ex_out_brk         ),
    .ov_o          (ex_out_ov          ),
    .adel_o        (ex_out_adel        ),
    .ades_o        (ex_out_ades        ),
    .tlbrel_o      (ex_out_tlbrel      ),
    .tlbres_o      (ex_out_tlbres      ),
    .tlbil_o       (ex_out_tlbil       ),
    .tlbis_o       (ex_out_tlbis       ),
    .tlbm_o        (ex_out_tlbm        ),

    .ft_adel_o     (ex_out_ft_adel     ),
    .ri_o          (ex_out_ri          ),
    .int_o         (ex_out_int         ),
    .badvaddr_o    (ex_out_badvaddr    ),
    .eret_o        (ex_out_eret        ),
    .bd_o          (ex_out_bd          ),
    .tlbp_o        (ex_out_tlbp        ),
    .tlbr_o        (ex_out_tlbr        ),
    .tlbwi_o       (ex_out_tlbwi       ),
    .tlbwr_o       (ex_out_tlbwr       ),

    .ex_redirect_taken(ex_redirect_taken),
    .ex_redirect_pc(ex_redirect_pc),

    .branch          (backend_branch          ),
    .branch_taken    (backend_branch_taken    ),
    .branch_pc       (backend_branch_pc       ),
    .branch_target_pc(backend_branch_target_pc),

    .ex_rf_wen  (ex_rf_wen  ),
    .ex_rf_wnum (ex_rf_wnum ),
    .ex_rf_wdata(ex_rf_wdata),

    .ex_ld (ex_ld ),
    .ex_mul(ex_mul),

    .mul_x   (mul_x   ),
    .mul_y   (mul_y   ),
    .mul_sign(mul_sign),
    
    .lsu_valid    (lsu_valid_i  ),
    .lsu_read_mem (lsu_read_mem ),
    .lsu_write_mem(lsu_write_mem),
    .lsu_ld_op    (lsu_ld_op    ),
    .lsu_st_op    (lsu_st_op    ),
    .lsu_addr     (lsu_addr     ),
    .lsu_rt       (lsu_rt       ),
    .lsu_ex_taken (lsu_ex_taken ),

    .stall_req_o  (stall_req_ex),
    .flush_req_o  (flush_req_ex),
    
    .wb_ex_taken (wb_out_ex_taken)
  );

  ex_wb_reg mycpu_ex_wb_reg(
    .clk(clk),
    .rst(rst),

    .stall(stall),
    .flush(flush),

    .ex_out_valid       (ex_out_valid       ),
    .ex_out_pc          (ex_out_pc          ),
    .ex_out_alu_result  (ex_out_alu_result  ),
    .ex_out_div_rs      (ex_out_div_rs      ),
    .ex_out_wr_mem      (ex_out_wr_mem      ),
    .ex_out_write_rf    (ex_out_write_rf    ),
    .ex_out_rf_waddr    (ex_out_rf_waddr    ),
    .ex_out_sel_rf_wdata(ex_out_sel_rf_wdata),
    .ex_out_write_hl    (ex_out_write_hl    ),
    .ex_out_sel_hl_wdata(ex_out_sel_hl_wdata),
    .ex_out_cp0_wsel    (ex_out_cp0_wsel    ),
    .ex_out_cp0_wreg_num(ex_out_cp0_wreg_num),
    .ex_out_cp0_wen     (ex_out_cp0_wen     ),
    .ex_out_cp0_wdata   (ex_out_cp0_wdata   ),
    .ex_out_cp0_rdata   (ex_out_cp0_rdata   ),
    .ex_out_ft_tlbre    (ex_out_ft_tlbre    ),
    .ex_out_ft_tlbi     (ex_out_ft_tlbi     ),
    .ex_out_sys         (ex_out_sys         ),
    .ex_out_brk         (ex_out_brk         ),
    .ex_out_ov          (ex_out_ov          ),
    .ex_out_adel        (ex_out_adel        ),
    .ex_out_ades        (ex_out_ades        ),
    .ex_out_tlbrel      (ex_out_tlbrel      ),
    .ex_out_tlbres      (ex_out_tlbres      ),
    .ex_out_tlbil       (ex_out_tlbil       ),
    .ex_out_tlbis       (ex_out_tlbis       ),
    .ex_out_tlbm        (ex_out_tlbm        ),
    .ex_out_ft_adel     (ex_out_ft_adel     ),
    .ex_out_ri          (ex_out_ri          ),
    .ex_out_int         (ex_out_int         ),
    .ex_out_badvaddr    (ex_out_badvaddr    ),
    .ex_out_eret        (ex_out_eret        ),
    .ex_out_bd          (ex_out_bd          ),

    .ex_out_tlbp        (ex_out_tlbp        ),
    .ex_out_tlbr        (ex_out_tlbr        ),
    .ex_out_tlbwi       (ex_out_tlbwi       ),
    .ex_out_tlbwr       (ex_out_tlbwr       ),

    .wb_in_valid       (wb_in_valid       ),
    .wb_in_pc          (wb_in_pc          ),
    .wb_in_alu_result  (wb_in_alu_result  ),
    .wb_in_div_rs      (wb_in_div_rs      ),
    .wb_in_wr_mem      (wb_in_wr_mem      ),
    .wb_in_write_rf    (wb_in_write_rf    ),
    .wb_in_rf_waddr    (wb_in_rf_waddr    ),
    .wb_in_sel_rf_wdata(wb_in_sel_rf_wdata),
    .wb_in_write_hl    (wb_in_write_hl    ),
    .wb_in_sel_hl_wdata(wb_in_sel_hl_wdata),
    .wb_in_cp0_wsel    (wb_in_cp0_wsel    ),
    .wb_in_cp0_wreg_num(wb_in_cp0_wreg_num),
    .wb_in_cp0_wen     (wb_in_cp0_wen     ),
    .wb_in_cp0_wdata   (wb_in_cp0_wdata   ),
    .wb_in_cp0_rdata   (wb_in_cp0_rdata   ),
    .wb_in_ft_tlbre    (wb_in_ft_tlbre    ),
    .wb_in_ft_tlbi     (wb_in_ft_tlbi     ),
    .wb_in_sys         (wb_in_sys         ),
    .wb_in_brk         (wb_in_brk         ),
    .wb_in_ov          (wb_in_ov          ),
    .wb_in_adel        (wb_in_adel        ),
    .wb_in_ades        (wb_in_ades        ),
    .wb_in_tlbrel      (wb_in_tlbrel      ),
    .wb_in_tlbres      (wb_in_tlbres      ),
    .wb_in_tlbil       (wb_in_tlbil       ),
    .wb_in_tlbis       (wb_in_tlbis       ),
    .wb_in_tlbm        (wb_in_tlbm        ),
    .wb_in_ft_adel     (wb_in_ft_adel     ),
    .wb_in_ri          (wb_in_ri          ),
    .wb_in_int         (wb_in_int         ),
    .wb_in_badvaddr    (wb_in_badvaddr    ),
    .wb_in_eret        (wb_in_eret        ),
    .wb_in_bd          (wb_in_bd          ),
    .wb_in_tlbp        (wb_in_tlbp        ),
    .wb_in_tlbr        (wb_in_tlbr        ),
    .wb_in_tlbwi       (wb_in_tlbwi       ),
    .wb_in_tlbwr       (wb_in_tlbwr       )
  );

  write_back mycpu_write_back(
    .clk (clk),
    .rst (rst),
    
    .valid_i       (wb_in_valid       ),
    .pc_i          (wb_in_pc          ),
    .alu_result_i  (wb_in_alu_result  ),
    .div_rs_i      (wb_in_div_rs      ),
    .wr_mem_i      (wb_in_wr_mem      ),
    .write_rf_i    (wb_in_write_rf    ),
    .rf_waddr_i    (wb_in_rf_waddr    ),
    .sel_rf_wdata_i(wb_in_sel_rf_wdata),
    .write_hl_i    (wb_in_write_hl    ),
    .sel_hl_wdata_i(wb_in_sel_hl_wdata),
    .cp0_wsel_i    (wb_in_cp0_wsel    ),
    .cp0_wreg_num_i(wb_in_cp0_wreg_num),
    .cp0_wen_i     (wb_in_cp0_wen     ),
    .cp0_wdata_i   (wb_in_cp0_wdata   ),
    .cp0_rdata_i   (wb_in_cp0_rdata   ),
    .ft_tlbre_i    (wb_in_ft_tlbre    ),
    .ft_tlbi_i     (wb_in_ft_tlbi     ),
    .sys_i         (wb_in_sys         ),
    .brk_i         (wb_in_brk         ),
    .ov_i          (wb_in_ov          ),
    .adel_i        (wb_in_adel        ),
    .ades_i        (wb_in_ades        ),
    .tlbrel_i      (wb_in_tlbrel      ),
    .tlbres_i      (wb_in_tlbres      ),
    .tlbil_i       (wb_in_tlbil       ),
    .tlbis_i       (wb_in_tlbis       ),
    .tlbm_i        (wb_in_tlbm        ),
    .ft_adel_i     (wb_in_ft_adel     ),
    .ri_i          (wb_in_ri          ),
    .int_i         (wb_in_int         ),
    .badvaddr_i    (wb_in_badvaddr    ),
    .eret_i        (wb_in_eret        ),
    .bd_i          (wb_in_bd          ),
    .tlbp_i        (wb_in_tlbp        ),
    .tlbr_i        (wb_in_tlbr        ),
    .tlbwi_i       (wb_in_tlbwi       ),
    .tlbwr_i       (wb_in_tlbwr       ),
    .lsu_stall_wb_i(lsu_stall_wb      ),

    .mul_result_i  (mul_result        ),
    .lsu_valid_i   (lsu_valid_o       ),
    .lsu_ld_data_i (lsu_ld_data       ),

    .pc_o      (wb_out_pc      ),
    .rf_wen_o  (wb_out_rf_wen  ),
    .rf_wnum_o (wb_out_rf_wnum ),
    .rf_wdata_o(wb_out_rf_wdata),
    .hl_wen_o  (wb_out_hl_wen  ),
    .hl_wdata_o(wb_out_hl_wdata),

    .bd_o          (wb_out_bd          ),
    .tlbre_taken_o (wb_out_tlbre_taken ),
    .ex_taken_o    (wb_out_ex_taken    ),
    .eret_taken_o  (wb_out_eret_taken  ),
    .ex_code_o     (wb_out_ex_code     ),
    .cp0_wen_o     (wb_out_cp0_wen     ),
    .cp0_wreg_num_o(wb_out_cp0_wreg_num),
    .cp0_wsel_o    (wb_out_cp0_wsel    ),
    .cp0_wdata_o   (wb_out_cp0_wdata   ),
    .addr_o        (wb_out_addr        ),
    .tlbp_taken_o  (wb_out_tlbp_taken  ),
    .tlbr_taken_o  (wb_out_tlbr_taken  ),
    .tlbwi_taken_o (wb_out_tlbwi_taken ),
    .tlbwr_taken_o (wb_out_tlbwr_taken ),

    .stall_req_o   (stall_req_wb ),
    .flush_req_o   (flush_req_wb ),
    .tlb_pc_o      (wb_out_tlb_pc),

    .write_rf_o     (wb_out_write_rf     ),
    .write_rf_data_o(wb_out_write_rf_data),
    .write_hl_o     (wb_out_write_hl     ),

    .ld_o (wb_out_ld),
    .mul_o (wb_out_mul)
  );

  hi_lo mycpu_hi_lo(
    .clk        (clk            ),
    .hi_lo_wdata(wb_out_hl_wdata),
    .hi_lo_wen  (wb_out_hl_wen),
    .hi_lo_raddr(hi_lo_raddr),

    .hi_lo_rdata(hi_lo_rdata)
  );

  debug mycpu_debug(
    .pc_i      (wb_out_pc      ),
    .rf_wen_i  (wb_out_rf_wen  ),
    .rf_wnum_i (wb_out_rf_wnum ),
    .rf_wdata_i(wb_out_rf_wdata),

    .debug_wb_pc      (debug_wb_pc      ),
    .debug_wb_rf_wen  (debug_wb_rf_wen  ),
    .debug_wb_rf_wnum (debug_wb_rf_wnum ),
    .debug_wb_rf_wdata(debug_wb_rf_wdata)
  );

  forward mycpu_forward(
    .wb_rf_wen  (wb_out_write_rf     ),
    .wb_rf_wnum (wb_out_rf_wnum      ),
    .wb_rf_wdata(wb_out_write_rf_data),
    .ex_rf_wen  (ex_rf_wen           ),
    .ex_rf_wnum (ex_rf_wnum          ),
    .ex_rf_wdata(ex_rf_wdata         ),
    .de_rs      (de_rs               ),
    .de_rt      (de_rt               ),

    .de_sel_rf_rdata_0(de_sel_rf_rdata_0),
    .de_sel_rf_rdata_1(de_sel_rf_rdata_1),
    .forward_data_ex  (forward_data_ex  ),
    .forward_data_wb  (forward_data_wb  )
  );

  hi_lo_forward mycpu_hi_lo_forward(
    .de_hl_raddr(hi_lo_raddr    ),
    .ex_hl_wen  (ex_out_write_hl),
    .ex_hl_wdata(ex_out_div_rs  ),
    .wb_hl_wen  (wb_out_write_hl),
    .wb_hl_wdata(wb_out_hl_wdata),

    .sel_hl_rdata(sel_hl_rdata),
    .hl_rdata_ex (hl_rdata_ex ),
    .hl_rdata_wb (hl_rdata_wb )
  );

  hazard mycpu_hazard(
    .stall_req_de   (stall_req_de   ),
    .stall_req_ex   (stall_req_ex   ),
    .stall_req_wb   (stall_req_wb   ),
    .de_valid       (if_out_valid   ),
    .ex_valid       (ex_in_valid    ),
    .wb_valid       (wb_in_valid    ),

    .flush_req_ex (flush_req_ex),
    .flush_req_wb (flush_req_wb),

    .stall(stall),
    .flush(flush)
  );

  mul mycpu_mul(
    .mul_clk(clk),
    .resetn(~rst),
    .mul_signed(mul_sign),
    .x(mul_x),
    .y(mul_y),

    .result(mul_result)
  );

  lsu mycpu_lsu(
    .clk(clk),
    .rst(rst),

    .lsu_valid_i    (lsu_valid_i    ),
    .lsu_read_mem   (lsu_read_mem   ),
    .lsu_write_mem  (lsu_write_mem  ),
    .lsu_ld_op      (lsu_ld_op      ),
    .lsu_st_op      (lsu_st_op      ),
    .lsu_addr       (lsu_addr       ),
    .lsu_rt         (lsu_rt         ),
    .lsu_ex_taken   (lsu_ex_taken   ),
    .lsu_stall_ex   (lsu_stall_ex   ),

    .data_vaddr(data_vaddr),
    .data_vaddr_valid(data_vaddr_valid),
    .is_store  (is_store  ),

    .data_paddr       (data_paddr       ),
    .data_paddr_valid (data_paddr_valid ),
    .data_uncache     (data_uncache     ),
    .data_tlb_refill  (data_tlb_refill  ),
    .data_tlb_invalid (data_tlb_invalid ),
    .data_tlb_modified(data_tlb_modified),

    .data_sram_req    (data_sram_req    ),
    .data_sram_addr_ok(data_sram_addr_ok),

    .data_sram_uncache(data_sram_uncache),
    .data_sram_wr     (data_sram_wr     ),
    .data_sram_size   (data_sram_size   ),
    .data_sram_addr   (data_sram_addr   ),
    .data_sram_wstrb  (data_sram_wstrb  ),
    .data_sram_wdata  (data_sram_wdata  ),

    .data_sram_data_ok(data_sram_data_ok),
    .data_sram_rdata  (data_sram_rdata  ),

    .lsu_valid_o    (lsu_valid_o    ),
    .lsu_ld_data    (lsu_ld_data    ),
    // .lsu_stall_wb   (lsu_stall_wb   ),

    .lsu_adel       (lsu_adel       ),
    .lsu_ades       (lsu_ades       ),
    .lsu_tlbrel     (lsu_tlbrel     ),
    .lsu_tlbres     (lsu_tlbres     ),
    .lsu_tlbil      (lsu_tlbil      ),
    .lsu_tlbis      (lsu_tlbis      ),
    .lsu_tlbm       (lsu_tlbm       ),
    .lsu_badvaddr   (lsu_badvaddr   )
  );

  cp0 mycpu_cp0(
    .clk(clk),
    .rst(rst),

    .ext_int(ext_int),

    .cp0_ex_pc(cp0_ex_pc),

    .bd          (wb_out_bd          ),
    .tlbre_taken (wb_out_tlbre_taken ),
    .pc          (wb_out_pc          ),
    .addr        (wb_out_addr        ),
    .ex_taken    (wb_out_ex_taken    ),
    .ex_code     (wb_out_ex_code     ),
    .eret_taken  (wb_out_eret_taken  ),
    .cp0_wen     (wb_out_cp0_wen     ),
    .cp0_wreg_num(wb_out_cp0_wreg_num),
    .cp0_wsel    (wb_out_cp0_wsel    ),
    .cp0_wdata   (wb_out_cp0_wdata   ),
    .tlbp_taken  (wb_out_tlbp_taken  ),
    .tlbr_taken  (wb_out_tlbr_taken  ),

    .cp0_rreg_num(cp0_rreg_num),
    .cp0_rsel    (cp0_rsel    ),

    .cp0_rdata(cp0_rdata),
    .cp0_rmask(cp0_rmask),
    .cp0_epc  (cp0_epc  ),
    .has_int  (has_int  ),

    .cp0_index_rdata   (cp0_index_rdata   ),
    .cp0_random_rdata  (cp0_random_rdata  ),
    .cp0_entrylo0_rdata(cp0_entrylo0_rdata),
    .cp0_entrylo1_rdata(cp0_entrylo1_rdata),
    .cp0_entryhi_rdata (cp0_entryhi_rdata ),
    .cp0_config0_rdata (cp0_config0_rdata ),

    .cp0_index_wdata   (cp0_index_wdata   ),
    .cp0_entrylo0_wdata(cp0_entrylo0_wdata),
    .cp0_entrylo1_wdata(cp0_entrylo1_wdata),
    .cp0_entryhi_wdata (cp0_entryhi_wdata )
  );

  cp0_forward mycpu_cp0_forward(
    .de_cp0_rreg_num(cp0_rreg_num),
    .de_cp0_rsel    (cp0_rsel    ),

    .ex_cp0_wen     (ex_out_cp0_wen     ),
    .ex_cp0_wreg_num(ex_out_cp0_wreg_num),
    .ex_cp0_wsel    (ex_out_cp0_wsel    ),
    .ex_cp0_wdata   (ex_out_cp0_wdata   ),

    .wb_cp0_wen     (wb_out_cp0_wen     ),
    .wb_cp0_wreg_num(wb_out_cp0_wreg_num),
    .wb_cp0_wsel    (wb_out_cp0_wsel    ),
    .wb_cp0_wdata   (wb_out_cp0_wdata   ),

    .sel_cp0_rdata(sel_cp0_rdata),
    .cp0_rdata_ex (cp0_rdata_ex ),
    .cp0_rdata_wb (cp0_rdata_wb )
  );

  assign tlbwi_taken = wb_out_tlbwi_taken;
  assign tlbwr_taken = wb_out_tlbwr_taken;

  backend_redirect mucpu_backend_redirect(
    .ex_redirect_taken(ex_redirect_taken),
    .ex_redirect_pc (ex_redirect_pc),
    .ex_pc          (cp0_ex_pc      ),
    .ex_taken       (wb_out_ex_taken   ),
    .eret_pc        (cp0_epc           ),
    .eret_taken     (wb_out_eret_taken ),
    .tlb_pc         (wb_out_tlb_pc     ),
    .tlbp_taken     (wb_out_tlbp_taken ),
    .tlbr_taken     (wb_out_tlbr_taken ),
    .tlbwi_taken    (wb_out_tlbwi_taken),
    .tlbwr_taken    (wb_out_tlbwr_taken),

    .backend_redirect_taken(backend_redirect_taken),
    .backend_redirect_is_br(backend_redirect_is_br),
    .backend_redirect_pc   (backend_redirect_pc   ),
    .backend_redirect_ds_pc(backend_redirect_ds_pc)
  );

  assign frontend_stall = stall[0];
  assign frontend_flush = backend_redirect_taken;
  assign dtlb0_flush = flush[1];
  assign dtlb0_stall = stall[1];
    
endmodule